package app

import (
	"chatgpt/helper"
	"chatgpt/helper/code"
	"chatgpt/logq"
	"chatgpt/model/app"
	"chatgpt/services/datasrv"
	"chatgpt/services/datasrv/sqlhelper"
	"context"
	"github.com/slclub/go-tips"
	"github.com/slclub/go-tips/array"
	"strings"
	"time"
)

// 商品
type ProductSrv struct {
}

func (self *ProductSrv) GetList(uid string, offset, limit int) []*app.Product {
	if limit == 0 {
		limit = 1000
	}
	conds := []*sqlhelper.CondItem{}
	formula := "{1} AND {2}"
	conds = append(conds, sqlhelper.WhereCond("Grounding", helper.GROUNDING_AT_1))
	conds = append(conds, sqlhelper.WhereCond("DeletedAt", 0))
	if uid != "" {
		conds = append(conds, sqlhelper.WhereCond("UUID", uid))
		formula += " AND {3}"
	}
	datas := self.GetListDB(&sqlhelper.Where{
		Conds:   conds,
		Order:   "updated_at DESC",
		Offset:  offset,
		Limit:   limit,
		Formula: formula,
	})
	if datas == nil {
		return datas
	}
	ids := []int{}
	array.DimensionPlugk(&ids, datas, "ProcID")

	var priceSrv PriceSrv
	prices := priceSrv.GetListWithIds(ids, 0)
	priceSrv.AttachMuch(datas, prices)

	return datas
}

func (self *ProductSrv) GetListDB(where *sqlhelper.Where) []*app.Product {
	res := sqlhelper.ResWhere{}
	mc := datasrv.AppDB.ProductSelect(context.Background(), &sqlhelper.ReqWhere{
		Where: where,
	}, &res)
	if res.MsgCode != code.SUCCESS {
		logq.InfoF("ProductSrv.GET code:%v", mc)
		return nil
	}
	data_arr, ok := res.Data.([]any)
	if !ok {
		return nil
	}

	rtn := []*app.Product{}
	for _, v := range data_arr {
		m, ok := v.(map[string]any)
		if !ok {
			continue
		}
		tmp := &app.Product{}
		tmp.ConvFromMap(m)
		rtn = append(rtn, tmp)
	}
	return rtn
}

func (self *ProductSrv) Save(p *app.Product) code.CODENO {
	res := sqlhelper.ResWhere{}
	mc := datasrv.AppDB.ProductSave(context.Background(), &sqlhelper.ReqWhere{
		Object: p.ConvToMap(),
		Where: &sqlhelper.Where{
			Conds: []*sqlhelper.CondItem{sqlhelper.WhereCond("ProcID", p.ProcID)},
		},
	}, &res)
	if res.MsgCode != code.SUCCESS {
		logq.InfoF("ProductSrv.SAVE code:%v", mc)
		return res.MsgCode
	}
	p.ConvFromMap(res.Data.(map[string]any))
	return code.SUCCESS
}

func (self *ProductSrv) First(product_id any) *app.Product {
	proc_id := tips.Int(product_id)
	if proc_id <= 0 {
		return nil
	}
	where := sqlhelper.Where{
		Conds: []*sqlhelper.CondItem{
			sqlhelper.WhereCond("ProcID", proc_id),
		},
	}
	proc := self.FirstDB(&where)
	var priceSrv PriceSrv
	prices := priceSrv.GetListWithIds([]int{int(proc.ProcID)}, 0)
	priceSrv.AttachOne(proc, prices)
	return proc
}

func (self *ProductSrv) FirstDB(where *sqlhelper.Where) *app.Product {
	res := sqlhelper.ResWhere{}
	mc := datasrv.AppDB.ProductFirst(context.Background(), &sqlhelper.ReqWhere{
		Where: where,
	}, &res)
	if res.MsgCode != code.SUCCESS {
		logq.InfoF("ProductSrv.First code:%v", mc)
		return nil
	}
	data_arr, ok := res.Data.(map[string]any)
	if !ok {
		return nil
	}
	rtn := &app.Product{}
	rtn.ConvFromMap(data_arr)
	return rtn
}

func (self *ProductSrv) TotalDB(where *sqlhelper.Where) int {
	res := sqlhelper.ResWhere{}
	mc := datasrv.AppDB.ProductTotal(context.Background(), &sqlhelper.ReqWhere{
		Where: where,
	}, &res)
	if res.MsgCode != code.SUCCESS {
		logq.InfoF("ProductSrv.First code:%v", mc)
		return 0
	}
	return tips.Int(res.Data)
}

// product event

type ProductVIPEvent struct {
}

func (self *ProductVIPEvent) Action() string {
	return app.BENEFIT_VIP
}

func (self *ProductVIPEvent) Exec(data map[string]any) code.CODENO {
	proc_any, ok := data["Proc"]
	if !ok {
		return code.PRODUCT_EVENT_NOT_EXIST
	}
	proc, ok := proc_any.(*app.Product)
	if !ok {
		return code.PRODUCT_EVENT_NOT_EXIST
	}
	uuid := tips.String(data["UUID"])
	if uuid == "" {
		return code.PRODUCT_EVENT_UID_EMPTY
	}
	proc.DecodeAction()
	goods_str := strings.Split(proc.BenefitGood, ",")
	goods := []int{}
	for _, v := range goods_str {
		goods = append(goods, tips.Int(v))
	}
	benefitSrv := BenefitSrv{}
	benefits := benefitSrv.GetListWithIDS(goods)
	for _, good := range benefits {
		e := self.eventDealBenefits(uuid, (good), proc.ActionMap)
		if e != code.SUCCESS {
			logq.InfoF("PRODUCT.DELIVER.ERROR code:%v err:%v", int(e), e)
		}
	}
	return code.SUCCESS
}

func (self *ProductVIPEvent) eventDealBenefits(uuid string, benfit *app.Benefit, action map[string]any) code.CODENO {
	if benfit == nil {
		return code.SUCCESS
	}
	switch benfit.Action {
	case app.BENEFIT_VIP:
		benefitSrv := BenefitSrv{}
		dur := tips.Int(action[app.BENEFIT_VIP])
		return benefitSrv.CallAttachWithID(uuid, benfit.BenefitID, time.Duration(dur))
	case app.BENEFIT_CASH:
		benefitSrv := BenefitSrv{}
		cash := tips.Int(action[app.BENEFIT_CASH])
		return benefitSrv.AttachWithCash(uuid, benfit, map[string]any{
			"cash": cash,
		})
	}
	return code.SUCCESS
}
